#include "store_app.h"

/*拟定用户名和密码 环境设备变量等 用于模拟讲解*/
char user_name[] = "Ligang";
char password[] = "123456";

/*消息类型*/
int msg_typ[N] = {1, 2, 3, 4};

/*进程间同步 P/V操作*/
void p(int semid, int sem_sum)
{
	struct sembuf sem;
	sem.sem_num = sem_sum;
	sem.sem_op = -1; // ｐ操作
	sem.sem_flg = 0;
	semop(semid, &sem, 1);
}

void v(int semid, int sem_sum)
{
	struct sembuf sem;
	sem.sem_num = sem_sum;
	sem.sem_op = 1; // V操作
	sem.sem_flg = 0;
	semop(semid, &sem, 1);
}

/*登录线程*/
void *login_thread(void *p)
{
	while (1)
	{
		sem_wait(&login_sem);
		printf("The login thread is activated, and a user wants to log in\n");
		/*操作数据库*/
		/*查找网页用户名与密码*/
		/*成功设置标志并回写消息*/

		/*案例*/
		if (0 == strncmp(user_name, login_msg.log_msg.name, strlen(user_name)) &&
			0 == strncmp(password, login_msg.log_msg.password, strlen(password)))
		{
			printf("login OK\n");
			memset(&login_msg, 0, sizeof(msg_t));
			/*设置登录标志，成功 flags==1 并设置消息类型*/
			login_msg.log_msg.flags = 1;
			login_msg.mtype = 5;
			msgsnd(msqid, &login_msg, sizeof(msg_t) - sizeof(long), 0);
		}
		else
		{
			printf("login ERROR\n");
			memset(&msg, 0, sizeof(msg_t));
			/*设置登录标志，失败 flags==0 并设置消息类型*/
			login_msg.log_msg.flags = 0;
			login_msg.mtype = 5;
			msgsnd(msqid, &login_msg, sizeof(msg_t) - sizeof(long), 0);
		}
		sem_post(&msg_sem);
	}
}

/*查看信息线程*/
void *env_view_thread(void *q)
{
	while (1)
	{
		sem_wait(&env_view_sem);
		printf("See the environment thread is activated and the warehouse environment data is sent to the web page\n");
		if (1 == view_msg.store_num)
		{
			printf("View warehouse 1 environment data\n");
			/*获取一号仓库环境传感器数据*/
			/*将环境传感器数据写入共享内存*/

			/*案例*/
			/*消息结构变量赋值 模拟读取设备数据*/
			printf("Execute P operation read data\n");
			view_msg.env_state_msg.tmp = env_tmp;
			view_msg.env_state_msg.hum = env_hum;
			view_msg.env_state_msg.illu = env_illu;
			view_msg.env_state_msg.led = env_led;
			view_msg.env_state_msg.fan = env_fan;
			view_msg.env_state_msg.beep = env_beep;

			/*写入共享内存*/
			p(semid, 0);
			memcpy(shm_addr, &view_msg, sizeof(msg_t));
			v(semid, 1);
			printf("Execute V operation data write shellmem\n");
		}
		else
		{
			printf("View warehouse 2 environment data\n");
			/*获取二号仓库环境传感器数据*/
			/*将环境传感器数据写入共享内存*/
		}
		sem_post(&msg_sem);
	}
}

/*设置阈值线程*/
void *env_set_thread(void *p)
{
	while (1)
	{
		sem_wait(&env_set_sem);
		printf("Setting the environment threshold The thread is activated to assign a value to the threshold variable\n");
		/*根据网页下传的阈值对环境阈值变量进行赋值*/
		/*设置温度上下限、湿度上下限、光强上下限等*/

		if (1 == set_msg.store_num)
		{
			/*给环境管理阈值变量赋值 环境管理线程根据阈值维护环境*/

			/*给环境参考变量赋值*/
			printf("tmp_up:%d\n", set_msg.env_set_msg.tmp_up);
			printf("tmp_dow:%d\n", set_msg.env_set_msg.tmp_dow);
			set_tmp_up = set_msg.env_set_msg.tmp_up;
			set_tmp_dow = set_msg.env_set_msg.tmp_dow;

			printf("hum_up:%d\n", set_msg.env_set_msg.hum_up);
			printf("hum_dow:%d\n", set_msg.env_set_msg.hum_dow);
			set_hum_up = set_msg.env_set_msg.hum_up;
			set_hum_dow = set_msg.env_set_msg.hum_dow;

			printf("tmp_up:%d\n", set_msg.env_set_msg.illu_up);
			printf("illu_dow:%d\n", set_msg.env_set_msg.illu_dow);
			set_illu_up = set_msg.env_set_msg.illu_up;
			set_illu_dow = set_msg.env_set_msg.illu_dow;
		}
		else
		{
			printf("二号仓库阈值设置\n");
		}
		sem_post(&msg_sem);
	}
}

/*设备控制线程*/
void *dev_ctrl_thread(void *p)
{
	while (1)
	{
		sem_wait(&dev_ctrl_sem);
		printf("The control device thread is activated, writing control information to the device file\n");
		/*操作对应设备*/
		/*一号仓库*/
		if (1 == ctrl_msg.store_num)
		{
			/*LED灯*/
			if (1 == ctrl_msg.dev_ctrl_msg.led)
			{
				printf("led ON\n");
				/*打开led*/
				led_buf[0] = 0;
				led_buf[1] = 1;
				write(ledfd, led_buf, sizeof(led_buf));

				env_led = 1;
			}
			else
			{
				printf("led OFF\n");
				led_buf[0] = 0;
				led_buf[1] = 0;
				write(ledfd, led_buf, sizeof(led_buf));
				env_led = 0;
			}
			/*风扇*/
			if (1 == ctrl_msg.dev_ctrl_msg.fan)
			{
				printf("fan ON\n");
				/*打开风扇*/

				env_fan = 1;
			}
			else
			{
				printf("fan OFF\n");
				env_fan = 0;
			}
			/*蜂鸣器*/
			if (1 == ctrl_msg.dev_ctrl_msg.beep)
			{
				printf("beep ON\n");
				/*打开蜂鸣器*/

				env_beep = 1;
			}
			else
			{
				printf("beep OFF\n");
				env_beep = 0;
			}
		}
		else
		{ /*二号仓库操作*/

			printf("二号仓库正在建设中\n");
			/*LED灯*/
			if (1 == ctrl_msg.dev_ctrl_msg.led)
			{
				printf("led ON\n");
			}
			else
			{
				printf("led OFF\n");
			}
			/*风扇*/
			if (1 == ctrl_msg.dev_ctrl_msg.fan)
			{
				printf("fan ON\n");
			}
			else
			{
				printf("fan OFF\n");
			}
			/*蜂鸣器*/
			if (1 == ctrl_msg.dev_ctrl_msg.beep)
			{
				printf("beep ON\n");
			}
			else
			{
				printf("beep OFF\n");
			}
		}

		sem_post(&msg_sem);
	}
}

/*获取消息线程*/
void *msg_thread(void *p)
{
	int ret, i = 0;
	while (1)
	{

		sem_wait(&msg_sem);
		memset(&msg, 0, sizeof(msg_t));
		ret = msgrcv(msqid, &msg, sizeof(msg_t) - sizeof(long), msg_typ[i], IPC_NOWAIT);
		if (-1 != ret)
		{
			switch (msg.mtype)
			{
			case 1:
				login_msg = msg;
				sem_post(&login_sem);
				printf("1 num thread\n");
				break;
			case 2:
				view_msg = msg;
				sem_post(&env_view_sem);
				printf("2 num thread\n");
				break;
			case 3:
				set_msg = msg;
				sem_post(&env_set_sem);
				printf("3 num thread\n");
				break;
			case 4:
				ctrl_msg = msg;
				sem_post(&dev_ctrl_sem);
				printf("4 num thread\n");
				break;
			default:
				break;
			}
		}
		i++;
		if (i == N)
		{
			i = 0;
		}
		sem_post(&msg_sem);
	}
}

/*线程初始化*/
int thread_init(void)
{
	int ret;
	// 初始化信号量
	if ((ret = sem_init(&msg_sem, 0, 1)) < 0)
	{
		puts("sem init error");
		return -1;
	}
	if ((ret = sem_init(&login_sem, 0, 0)) < 0)
	{
		puts("sem init error");
		return -1;
	}
	if ((ret = sem_init(&env_view_sem, 0, 0)) < 0)
	{
		puts("sem init error");
		return -1;
	}
	if ((ret = sem_init(&env_set_sem, 0, 0)) < 0)
	{
		puts("sem init error");
		return -1;
	}
	if ((ret = sem_init(&dev_ctrl_sem, 0, 0)) < 0)
	{
		puts("sem init error");
		return -1;
	}

	/*创建登录线程*/
	if ((ret = pthread_create(&tid, NULL, login_thread, NULL)) < 0)
	{
		fprintf(stderr, "pthread_create = %s\n", strerror(ret));
		return -1;
	}

	/*创建查看环境线程*/
	if ((ret = pthread_create(&tid, NULL, env_view_thread, NULL)) < 0)
	{
		fprintf(stderr, "pthread_create = %s\n", strerror(ret));
		return -1;
	}

	/*创建设置阈值线程*/
	if ((ret = pthread_create(&tid, NULL, env_set_thread, NULL)) < 0)
	{
		fprintf(stderr, "pthread_create = %s\n", strerror(ret));
		return -1;
	}

	/*创建设备控制线程*/
	if ((ret = pthread_create(&tid, NULL, dev_ctrl_thread, NULL)) < 0)
	{
		fprintf(stderr, "pthread_create = %s\n", strerror(ret));
		return -1;
	}

	/*创建等待消息线程*/
	if ((ret = pthread_create(&tid, NULL, msg_thread, NULL)) < 0)
	{
		fprintf(stderr, "pthread_create = %s\n", strerror(ret));
		return -1;
	}

	return 0;
}

/*共享内存初始化*/
int shm_init(void)
{
	/*创建共享内存*/
	if ((key = ftok("/home/linux", 'm')) == -1)
	{
		perror("ftok");
		return -1;
	}

	shmid = shmget(key, sizeof(msg_t), IPC_CREAT | 0666);
	if (shmid == -1)
	{
		perror("shmid");
		return -1;
	}

	/*映射共享内存地址空间*/
	shm_addr = (msg_t *)shmat(shmid, NULL, 0);
	if (shm_addr == (void *)-1)
	{
		perror("shmat");
		return -1;
	}

	/*创建信号灯集*/
	semid = semget(key, 2, IPC_CREAT | 0666);

	/*初始化信号灯*/
	union semun sem;
	sem.val = 1;
	semctl(semid, 0, SETVAL, sem);

	return 0;
}

/*消息队列初始化*/
int msgqueue_init(void)
{
	/*创建消息队列*/
	if ((key = ftok("/home/linux", 'a')) == -1)
	{
		perror("ftok");
		return -1;
	}

	msqid = msgget(key, IPC_CREAT | 0666);
	if (msqid == -1)
	{
		perror("msgget");
		return -1;
	}

	return 0;
}

/*系统初始化*/
int sys_init(void)
{
	int ret;

	/*线程初始化*/
	ret = thread_init();
	if (-1 == ret)
	{

		puts("线程初始化失败");
		return -1;
	}

	/*消息队列初始化*/
	ret = msgqueue_init();
	if (-1 == ret)
	{

		puts("消息队列初始化失败");
		return -1;
	}

	/*共享内存初始化*/
	ret = shm_init();
	if (-1 == ret)
	{

		puts("共享内存初始化失败");
		return -1;
	}

	return 0;
}
